﻿using System;
using System.Windows.Input;
using Oxage.Common;
using Oxage.Services;
using ICSharpCode.AvalonEdit.Editing;

namespace Oxage.Commands
{
	public class EditCommand : ICommand
	{
		#region Constructor
		public EditCommand()
		{
			TextEditorService.ActiveTextEditorChanged += (s, args) =>
			{
				//Detach events from previous instance
				if (args.OldValue != null)
				{
					args.OldValue.TextChanged -= (sender, e) => OnCanExecuteChanged();
					args.OldValue.TextArea.SelectionChanged -= (sender, e) => OnCanExecuteChanged();
				}

				//Attach events
				if (args.NewValue != null)
				{
					args.NewValue.TextChanged += (sender, e) => OnCanExecuteChanged();
					args.NewValue.TextArea.SelectionChanged += (sender, e) => OnCanExecuteChanged();
				}
			};

			var editor = TextEditorService.ActiveTextEditor;
			if (editor != null)
			{
				//Track changes
				editor.TextChanged += (sender, e) => OnCanExecuteChanged();
				editor.TextArea.SelectionChanged += (sender, e) => OnCanExecuteChanged();
			}
		}
		#endregion

		#region ICommand Members
		public bool CanExecute(object parameter)
		{
			var editor = TextEditorService.ActiveTextEditor;
			if (editor == null)
			{
				return false;
			}

			var command = parameter as string;
			switch (command)
			{
				case "Undo":
					return editor.CanUndo;

				case "Redo":
					return editor.CanRedo;

				case "Cut":
				case "Copy":
				case "Delete":
					return editor.SelectionLength > 0;
			}

			return true;
		}

		public event EventHandler CanExecuteChanged;
		protected virtual void OnCanExecuteChanged()
		{
			if (CanExecuteChanged != null)
			{
				CanExecuteChanged(this, new EventArgs());
			}
		}

		public void Execute(object parameter)
		{
			var editor = TextEditorService.ActiveTextEditor;
			if (editor == null)
			{
				return;
			}

			var command = parameter as string;
			switch (command)
			{
				case "Undo":
					if (editor.CanUndo)
					{
						editor.Undo();
					}
					break;

				case "Redo":
					if (editor.CanRedo)
					{
						editor.Redo();
					}
					break;

				case "Cut":
					editor.Cut();
					break;

				case "Copy":
					editor.Copy();
					break;

				case "Paste":
					editor.Paste();
					break;

				case "Delete":
					editor.DeleteSelected();
					break;

				case "FindText":
					DialogService.Find();
					break;

				case "FindNext":
					DialogService.FindNext();
					break;

				case "ReplaceText":
					DialogService.Replace();
					break;

				case "JumpToLine":
					DialogService.JumpToLine();
					break;
			}
		}
		#endregion
	}
}
